package com.example.springbootdemo.beandefinationregister;

import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;
import java.util.Set;

public class MapperImportBeanDefinationRegister implements ImportBeanDefinitionRegistrar {

    private static Class targetClass = MapperFactoryBean.class;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        AnnotationAttributes attributes = (AnnotationAttributes) importingClassMetadata.getAnnotationAttributes(EnableMapper.class.getName());
        if(attributes == null) {
            return;
        }
        String pkgName = attributes.getString("pkgName");

        MapperClassPathScanner scanner = new MapperClassPathScanner(registry);
        scanner.addIncludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                return true;
            }
        });

        Set<BeanDefinitionHolder> beanDefinitionHolders = scanner.doScan(pkgName);
        for(BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
            GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
            String sourceClass = beanDefinition.getBeanClassName();
            beanDefinition.setBeanClass(targetClass);
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(sourceClass);
        }
    }
}
